﻿#region using statements

using System;
using System.IO;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using NGen;
using NGen.Managers.Pathfinding;

#endregion

namespace TowerDefense.Misc
{
	/// <summary>
	/// 	Represents the current level in the game
	/// </summary>
	public class GameLevel
	{
		public GameLevel(string p_mapName) {
			// load the level map
			LevelImage = GameEngine.GameContent.Load<Texture2D>("Content\\Textures\\Level\\" + p_mapName);

			// load the tile map from a file, used to allow enemies to follow the path
			LevelGrid = new int[LevelWidth,LevelHeight];
			var reader = new StreamReader("Content\\LevelMaps\\" + p_mapName + ".dat");
			var line = reader.ReadLine();
			StartPosition = new Point(int.Parse(line.Split(' ')[0]), int.Parse(line.Split(' ')[1]));
			line = reader.ReadLine();
			EndPosition = new Point(int.Parse(line.Split(' ')[0]), int.Parse(line.Split(' ')[1]));

			var j = 0;
			while((line = reader.ReadLine()) != null) {
				//populate the 2d level tile map
				var i = 0;
				//for each line, split into a string array on each space
				foreach(var value in line.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)) {
					LevelGrid[i++, j] = int.Parse(value);
				}
				++j;
			}
		}

		/// <summary>
		/// 	get height of level in tiles
		/// </summary>
		public static int LevelHeight {
			get { return 18; }
		}

		/// <summary>
		/// 	get width of level in tiles
		/// </summary>
		public static int LevelWidth {
			get { return 18; }
		}

		/// <summary>
		/// 	get size of tiles in pixels
		/// </summary>
		public static int LevelTilesize {
			get { return 32; }
		}

		/// <summary>
		/// 	Get offset from top left corner
		/// </summary>
		public static Vector2 MapOffset {
			get { return new Vector2(12, 12); }
		}

		/// <summary>
		/// 	get the level image
		/// </summary>
		public Texture2D LevelImage { get; protected set; }

		/// <summary>
		/// 	get the level tile map
		/// </summary>
		public int[,] LevelGrid { get; protected set; }

		/// <summary>
		/// 	get the level start position
		/// </summary>
		public Point StartPosition { get; protected set; }

		/// <summary>
		/// 	get the level end position
		/// </summary>
		public Point EndPosition { get; protected set; }

		/// <summary>
		/// 	convert level grid coordinates to pixel coordinates
		/// </summary>
		/// <param name = "p_position"></param>
		/// <returns></returns>
		public static Vector2 GetScreenCoords(Point p_position) {
			var coord = new Vector2 {
				X = MapOffset.X + (p_position.X * LevelTilesize),
				Y = MapOffset.Y + (p_position.Y * LevelTilesize)
			};
			return coord;
		}

		/// <summary>
		/// 	convert pixel coordinates to level grid coordinates
		/// </summary>
		/// <param name = "p_position"></param>
		/// <returns></returns>
		public static Point GetWorldCoords(Vector2 p_position) {
			var coord = new Point {
				X = (int) ((p_position.X - MapOffset.X) / LevelTilesize),
				Y = (int) ((p_position.Y - MapOffset.Y) / LevelTilesize)
			};
			return coord;
		}

		/// <summary>
		/// 	snap the passed in pixel coordinates to the nearest level grid coordinate.
		/// 	vector is passed by reference and modified
		/// </summary>
		/// <param name = "p_position">the vector to manipulate</param>
		public static void SnapToGrid(ref Vector2 p_position) {
			p_position.X = p_position.X - (p_position.X % LevelTilesize) + MapOffset.X;
			p_position.Y = p_position.Y - (p_position.Y % LevelTilesize) + MapOffset.Y;
		}

		/// <summary>
		/// 	Returns the level coordinates which correspond to the path which
		/// 	enemies follow
		/// </summary>
		/// <returns>the path to follow</returns>
		public Point[] GetEnemyPath() {
			//create the grid to pass into the pathfinding manager
			var gridCopy = new bool[LevelWidth,LevelHeight];
			for(var i = 0; i < LevelWidth; i++) {
				for(var j = 0; j < LevelWidth; j++) {
					gridCopy[i, j] = LevelGrid[i, j] == 0;
				}
			}

			//initialize the pathfinding manager
			GameEngine.GetService<IManagerPathfinding>().SetParams(LevelWidth, LevelHeight, 1, //cost to move to an adjacent cell
			                                                       0, //cost to move diagonally (0 disables diagonal movement)
			                                                       gridCopy);

			//return the path which is returned by the pathfinding manager
			return GameEngine.GetService<IManagerPathfinding>().FindPath(StartPosition, EndPosition);
		}
	}
}